<template>
  <view class="container">
    <!-- 聊天内容区域 -->
    <scroll-view
      class="chat-container"
      scroll-y
      :scroll-top="scrollTop"
      @scroll="scrollHandle"
      scroll-with-animation
      ref="scrollView"
    >
      <view
        v-for="(item, index) in messageList"
        :key="index"
        class="message-item"
        :class="[item.type === 'user' ? 'send' : 'receive']"
      >
        <!-- 头像 -->
        <image
          :src="
            item.type === 'user'
              ? userInfo.avatar == ''
                ? '../../static/missing-face.png'
                : userInfo.avatar
              : '../../static/mine/live.png'
          "
          :class="['avatar', adminStatusClosed ? 'closed' : '']"
        />

        <view class="message-content">
          <!-- 订单消息 -->
          <view v-if="item.contentType === 'order'" class="order-card">
            <text class="order-title">订单信息</text>
            <text class="order-no">订单号：{{ item.content.orderNo }}</text>
            <text class="order-price">金额：{{ item.content.price }}元</text>
          </view>

          <!-- 图片消息 -->
          <image
            v-else-if="item.contentType === 'image'"
            :src="item.content"
            mode="widthFix"
            class="chat-image"
            @click="previewImage(item.content)"
          />

          <!-- 文本消息 -->
          <view v-else class="message-text">{{ item.content }}</view>

          <view class="message-time">{{ item.time }}</view>
        </view>
      </view>
    </scroll-view>

    <!-- 底部操作栏 -->
    <view class="input-container">
      <view class="input-box">
        <image src="../../static/mine/tupian.svg" class="icon-image" @click="chooseImage" />
        <image src="../../static/mine/dingdan.svg" class="icon-order" @click="sendOrder" />
        <input v-model="inputValue" class="input" placeholder="输入消息内容" @confirm="sendMessage" />
        <button class="send-btn" @click="sendMessage">发送</button>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      inputValue: '',
      userInfo: {},
      messageList: [],
      scrollTop: 0,
      scrollTimer: null,
      inputTimer: null,
      socket: {
        wss: 'ws://localhost:8899/ws',
        task: {},
        heartbeatTimer: null
      },
      adminStatusClosed: true,
      fromToID: {
        from: '',
        to: ''
      }
    }
  },
  watch: {
    messageList() {
      setTimeout(() => {
        this.scrollToBottom()
      }, 10)
    }
  },
  onLoad() {
    this.userInfo = getApp().globalData.userInfo
    this.connectSocket()
  },
  methods: {
    connectSocket() {
      this.socket.task = uni.connectSocket({
        url: this.socket.wss,
        header: {
          'content-type': 'application/json',
          Authorization: getApp().globalData.Authorization
        },
        method: 'GET',
        complete: () => {}
      })

      this.socket.task.onerror = (error) => {
        console.error('WebSocket错误:', error)
      }

      // websocket必须保持打开状态才能正常发送接收消息，所以send和onmessage这两个操作都应该在onpen的情况下进行

      this.socket.task.onOpen((res) => {
        // console.log('socket已经打开')

        const msg = {
          type: 'first',
          content_type: 'text',
          content: '',
          to_id: '',
          time: new Date()
        }

        // 发送第一次链接
        this.socket.task.send({
          data: JSON.stringify(msg)
        })

        this.startHeartbeat()
      })

      // console.log(this.socket.task)
      this.socket.task.onMessage((res) => {
        console.log('收到消息', res)
        const result = JSON.parse(res.data)
        switch (result.type) {
          case 'heartbeat':
            console.log('socket心跳')
            console.log(result)
            this.fromToID.from = result.content.id
            this.fromToID.to = result.content.toId
            this.adminStatusClosed = result.content.adminStatusClosed
            break
          case 'admin':
          case 'user':
            console.log('收到')
            this.messageList.push(result)
            break
          case 'first':
            console.log(result)
            this.fromToID.from = result.content.id
            this.fromToID.to = result.content.toId
            this.adminStatusClosed = result.content.adminStatusClosed
            break
          default:
            console.log(result)
        }
      })
    },

    sendMessage() {
      if (!this.inputValue.trim()) return

      // 关闭心跳
      if (this.inputTimer) {
        clearTimeout(this.socket.heartbeatTimer)
        clearTimeout(this.inputTimer)
      } else {
        clearTimeout(this.socket.heartbeatTimer)
      }

      // console.log('aasds')

      const msg = {
        content: this.inputValue,
        content_type: 'text',
        type: 'user',
        time: new Date(),
        to_id: this.fromToID.to,
        from_id: this.fromToID.from
      }

      console.log(msg)

      this.socket.task.send({
        data: JSON.stringify(msg)
      })
      this.inputValue = ''
      // 定时开启心跳
      this.inputTimer = setTimeout(() => {
        this.startHeartbeat()
      }, 3000)
    },
    chooseImage() {
      uni.chooseImage({
        count: 1,
        success: (res) => {
          const tempFilePaths = res.tempFilePaths
          const msg = {
            content: tempFilePaths[0],
            contentType: 'image',
            type: 'send',
            time: this.getTime()
          }
          this.messageList.push(msg)
          // this.scrollToBottom()
        }
      })
    },
    sendOrder() {
      const order = {
        orderNo: 'DD202405280001',
        price: 299.0
      }
      const msg = {
        content: order,
        contentType: 'order',
        type: 'send',
        time: this.getTime()
      }
      this.messageList.push(msg)
    },
    previewImage(url) {
      uni.previewImage({
        urls: [url]
      })
    },

    startHeartbeat() {
      // 清除旧定时器
      if (this.socket.heartbeatTimer) {
        clearInterval(this.socket.heartbeatTimer)
        this.socket.heartbeatTimer = null
      }

      // 每20秒跳动一下
      this.socket.heartbeatTimer = setInterval(() => {
        if (this.socket.task && this.socket.task.readyState === 1) {
          this.socket.task.send({
            data: JSON.stringify({ type: 'heartbeat' })
          })
        } else {
          clearInterval(this.socket.heartbeatTimer)
        }
      }, 20000)
    },

    getTime() {
      const now = new Date()
      return `${now.getHours()}:${now.getMinutes().toString().padStart(2, '0')}`
    },
    scrollHandle(e) {
      this.oldScrollTop = e.detail.scrollTop
    },

    parseTime(timeStr) {
      const [hours, minutes] = timeStr.split(':')
      const date = new Date()
      date.setHours(hours)
      date.setMinutes(minutes)
      return date.getTime()
    },
    // 增强版滚动到底部方法
    async scrollToBottom() {
      try {
        // 等待渲染完成
        await this.$nextTick()

        // 获取滚动容器信息
        const query = uni.createSelectorQuery().in(this)
        query.select('.chat-container').boundingClientRect()
        query.select('.chat-container').scrollOffset()
        query.exec((res) => {
          if (res && res[1]) {
            // 计算目标滚动位置
            const containerHeight = res[0].height
            const scrollHeight = res[1].scrollHeight
            const targetTop = scrollHeight - containerHeight

            // 增加容错判断
            if (Math.abs(this.scrollTop - targetTop) > 1) {
              this.scrollTop = targetTop + Math.random() + 10 // 添加随机数强制触发刷新
            }
          }
        })
      } catch (e) {
        console.error('滚动异常:', e)
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.container {
  height: 100vh;
  display: flex;
  flex-direction: column;
  background-color: #f5f5f5;
}

.chat-container {
  width: 100%;
  // flex: 1;
  height: calc(100vh - 120upx);
  box-sizing: border-box;
  padding: 0 20upx;
  padding-top: 20upx;

  // overflow-anchor: bottom;
}

.message-item {
  margin: 20upx 0;
  display: flex;
  align-items: flex-start;
  position: relative;

  &.send {
    flex-direction: row-reverse;

    .avatar {
      margin-left: 20upx;
    }

    .message-content {
      align-items: flex-end;
    }

    .message-text {
      background-color: #95ec69;
      border-radius: 20upx 0 20upx 20upx;
    }
  }

  &.receive {
    .avatar {
      margin-right: 20upx;
      display: flex;
      justify-content: center;
      position: relative;
    }

    .closed::after {
      content: '离线';

      height: 100%;
      width: 100%;
      background-color: rgba(255, 255, 255, 0.7);
      font-size: 25upx;
      position: absolute;
      top: 0%;
      left: 0%;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    .message-content {
      align-items: flex-start;
    }

    .message-text {
      background-color: #ffffff;
      border-radius: 0 20upx 20upx 20upx;
    }
  }
}

.avatar {
  width: 80upx;
  height: 80upx;
  border-radius: 10upx;
  flex-shrink: 0;
}

.message-content {
  max-width: 75%;
  margin: 0 20upx;
}

.message-text {
  padding: 20upx;
  font-size: 28upx;
  line-height: 1.5;
  color: #333;
  min-width: 100upx;
  background-color: rgba(149, 236, 105, 0.9);
  position: relative;
}

.message-time {
  font-size: 24upx;
  color: #999;
  margin-top: 8upx;
}

.chat-image {
  max-width: 300upx;
  border-radius: 10upx;
}

.order-card {
  background: #fff;
  padding: 20upx;
  border-radius: 10upx;
  width: 400upx;
  box-shadow: 0 4upx 12upx rgba(0, 0, 0, 0.1);

  .order-title {
    font-size: 32upx;
    font-weight: bold;
    display: block;
    margin-bottom: 15upx;
  }

  .order-no,
  .order-price {
    font-size: 28upx;
    color: #666;
    display: block;
    line-height: 1.5;
  }
}

.input-container {
  width: 100%;
  height: 120upx;
  background-color: #07c160;
  box-sizing: border-box;
}

.input-box {
  background-color: #fff;
  padding: 20upx;
  box-sizing: border-box;
  border-top: 1upx solid #eee;
  width: 100%;

  height: 120upx;
  display: flex;
  align-items: center;
  gap: 20upx;
  position: fixed;
  bottom: 0;
  left: 0;

  .icon-image,
  .icon-order {
    width: 50upx;
    height: 50upx;
  }

  .input {
    flex: 1;
    background: #f5f5f5;
    border-radius: 40upx;
    padding: 15upx 25upx;
    font-size: 28upx;
  }

  .send-btn {
    background: #07c160;
    color: #fff;
    border-radius: 40upx;
    padding: 0 30upx;
    font-size: 28upx;
    line-height: 2;
  }
}
</style>
